/*
 * CBasicDemo.h
 *
 *  Created on: Sep 23, 2011
 *      Author: welcome
 */
#include <btBulletCollisionCommon.h>
#include <btBulletDynamicsCommon.h>
#include <BulletCollision/CollisionShapes/btShapeHull.h>
#include <BulletCollision/CollisionShapes/btConvexPolyhedron.h>
#include <GLES/gl.h>

#ifndef CBASICDEMO_H_
#define CBASICDEMO_H_

namespace GGEngine {

#define SCALING 1.
#define START_POS_X -5
#define START_POS_Y -5
#define START_POS_Z -3

#define ARRAY_SIZE_X 5
#define ARRAY_SIZE_Y 5
#define ARRAY_SIZE_Z 5

#define MAX_PROXIES (ARRAY_SIZE_X*ARRAY_SIZE_Y*ARRAY_SIZE_Z + 1024)

class GlDrawcallback: public btTriangleCallback {

public:

	bool m_wireframe;

	GlDrawcallback() :
		m_wireframe(false) {
	}

	virtual void processTriangle(btVector3* triangle, int partId,
			int triangleIndex) {

		(void) triangleIndex;
		(void) partId;

		if (m_wireframe) {
			//			glBegin(GL_LINES);
			//			glColor3f(1, 0, 0);
			//			glVertex3d(triangle[0].getX(), triangle[0].getY(), triangle[0].getZ());
			//			glVertex3d(triangle[1].getX(), triangle[1].getY(), triangle[1].getZ());
			//			glColor3f(0, 1, 0);
			//			glVertex3d(triangle[2].getX(), triangle[2].getY(), triangle[2].getZ());
			//			glVertex3d(triangle[1].getX(), triangle[1].getY(), triangle[1].getZ());
			//			glColor3f(0, 0, 1);
			//			glVertex3d(triangle[2].getX(), triangle[2].getY(), triangle[2].getZ());
			//			glVertex3d(triangle[0].getX(), triangle[0].getY(), triangle[0].getZ());
			//			glEnd();
		} else {
			//			glBegin(GL_TRIANGLES);
			//
			//			glVertex3d(triangle[0].getX(), triangle[0].getY(), triangle[0].getZ());
			//			glVertex3d(triangle[1].getX(), triangle[1].getY(), triangle[1].getZ());
			//			glVertex3d(triangle[2].getX(), triangle[2].getY(), triangle[2].getZ());
			//
			//			glVertex3d(triangle[2].getX(), triangle[2].getY(), triangle[2].getZ());
			//			glVertex3d(triangle[1].getX(), triangle[1].getY(), triangle[1].getZ());
			//			glVertex3d(triangle[0].getX(), triangle[0].getY(), triangle[0].getZ());
			//			glEnd();
		}
	}
};

class CBasicDemo {

protected:
	struct ShapeCache {
		struct Edge {
			btVector3 n[2];
			int v[2];
		};
		btShapeHull m_shapehull;
		ShapeCache(btConvexShape* s) :
			m_shapehull(s) {
		}
		btAlignedObjectArray<Edge> m_edges;
	};

	btAlignedObjectArray<ShapeCache*>	m_shapecaches;
public:
	CBasicDemo();
	virtual ~CBasicDemo();

	void initPhysics();

	void exitPhysics();

	btDynamicsWorld* getDynamicsWorld() {
		return m_dynamicsWorld;
	}

	void initGraphic();

	void animate();

	void setScreenWidth(int screenWidth) {
		m_screenWidth = screenWidth;
	}

	void setScreenHeight(int screenHeight) {
		m_screenHeight = screenHeight;
	}
	int getDebugMode() {
		return m_debugMode;
	}

	void setDebugMode(int mode) {
		this->m_debugMode = mode;
	}
	void setShadows(bool enable) {
		m_enableshadows = enable;
	}
	void setCameraDistance(float dist) {
		m_cameraDistance = dist;
	}
	void reshape(int w, int h);

	void shootBox(const btVector3& destination);

	btVector3 getRayTo(int x, int y);

	btVector3 getCameraTargetPosition() {
		return m_cameraTargetPosition;
	}
	ShapeCache* cache(btConvexShape*);
private:

	void drawOpenGL(btScalar* m, const btCollisionShape* shape,
			const btVector3& color, int debugMode,
			const btVector3& worldBoundsMin, const btVector3& worldBoundsMax);

	void setShootBoxShape();

	btVector3 getCameraPosition() {
		return m_cameraPosition;
	}

	btRigidBody* localCreateRigidBody(float mass,
			const btTransform& startTransform, btCollisionShape* shape);

	void gluLookAt(GLfloat eyex, GLfloat eyey, GLfloat eyez, GLfloat centerx,
			GLfloat centery, GLfloat centerz, GLfloat upx, GLfloat upy,
			GLfloat upz);

	void updateCamera();

	void renderScene(int pass);

	btAlignedObjectArray<btCollisionShape*> m_collisionShapes;

	btBroadphaseInterface* m_broadphase;

	btCollisionDispatcher* m_dispatcher;

	btConstraintSolver* m_solver;

	btDefaultCollisionConfiguration* m_collisionConfiguration;

	btDynamicsWorld* m_dynamicsWorld;
	btVector3 m_cameraPosition;
	btVector3 m_cameraUp;
	btVector3 m_cameraTargetPosition;

	float m_ele;
	float m_azi;
	float m_cameraDistance;
	int m_forwardAxis;
	int m_screenWidth;
	int m_screenHeight;
	int m_ortho;
	float m_frustumZNear;
	float m_frustumZFar;
	bool m_enableshadows;

	int m_debugMode;

	btScalar m_defaultContactProcessingThreshold;
	float m_ShootBoxInitialSpeed;
	btCollisionShape* m_shootBoxShape;
	bool m_textureenabled;
	bool m_textureinitialized;
	unsigned int m_texturehandle;

};

}

#endif /* CBASICDEMO_H_ */
